package hichecker.university;

import hichecker.controller.MainController;
import hichecker.ui.components.icon_factory.IconFactory.IconType;
import hichecker.ui.custom_views.passing.PassingCondition.ConditionType;
import hichecker.ui.general_views.container_panel.content.ContentPanel;
import hichecker.university.jaxb.HashMapAdapter;

import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.UUID;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

/**
 * Class representing a task a series contains of
 */
@XmlType(propOrder = {"id", "gainedPoints"})
public class Task extends UniversityPart {

	private @XmlAttribute String name;
	private @XmlAttribute float maxPoints;
	private @XmlAttribute boolean isOptional;

	private @XmlJavaTypeAdapter(HashMapAdapter.class) HashMap<Student, Float> gainedPoints;
	private @XmlElement UUID id;

	/**
	 * Creates a new task and generates a new unique id
	 */
	public Task() {
		id = UUID.randomUUID();
	}

	/**
	 * Creates a new task and copies all values out of the referenced task
	 *
	 * @param task
	 */
	public Task(Task task) {
		id = task.getID();
		name = task.getName();
		maxPoints = task.getMaxPoints();
		isOptional = task.isOptional;

		gainedPoints = new HashMap<Student, Float>();
		for (Entry<Student, Float> e : task.getGainedPoints().entrySet())
			gainedPoints.put(e.getKey(), e.getValue());
	}

	@Override
	@XmlTransient
	public UUID getID() {
		return id;
	}

	/**
	 * @param id the unique id to set
	 */
	public void setID(UUID id) {
		this.id = id;
	}

	@Override
	@XmlTransient
	public String getName() {
		return name;
	}

	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return the maximum of gainable points
	 */
	@XmlTransient
	public float getMaxPoints() {
		return maxPoints;
	}

	/**
	 * @param maxPoints the maximum points to set
	 */
	public void setMaxPoints(float maxPoints) {
		this.maxPoints = maxPoints;
	}

	/**
	 * @return the gained points of all students
	 */
	@XmlTransient
	public HashMap<Student, Float> getGainedPoints() {
		return gainedPoints =
			(gainedPoints == null ? new HashMap<Student, Float>()
					: gainedPoints);
	}

	/**
	 * Returns the gained points of the referenced student
	 *
	 * @param student
	 * @return -1 if the points for this student haven't been set yet (this is unequal to: the
	 *         student has 0 points!)
	 */
	public float getGainedPoints(Student student) {
		if (gainedPoints == null) gainedPoints = new HashMap<Student, Float>();
		return gainedPoints.get(student) == null ? -1 : gainedPoints.get(student);
	}

	/**
	 * @param gainedPoints the gained points to set for all students
	 */
	public void setGainedPoints(HashMap<Student, Float> gainedPoints) {
		this.gainedPoints = gainedPoints;
	}

	/**
	 * @param student
	 *            the student the points belong to
	 * @param gainedPoints
	 *            the gained points to set
	 */
	public void setGainedPoints(Student student, float gainedPoints) {
		if (this.gainedPoints == null) this.gainedPoints = new HashMap<Student, Float>();
		this.gainedPoints.put(student, gainedPoints);
	}

	/**
	 * Indicates whether a task is optional and its points aren't needed for full points in the
	 * series
	 *
	 * @return
	 */
	@XmlTransient
	public boolean isOptional() {
		return isOptional;
	}

	/**
	 * @param isOptional sets whether the task is optinal
	 */
	public void setOptional(boolean isOptional) {
		this.isOptional = isOptional;
	}

	@Override
	public List<ConditionType> getPossibleConditions() {
		return null;
	}

	@Override
	public List<UniversityPart> getSubParts() {
		return null;
	}

	@Override
	public UniversityPart[] getPossibleSubPart() {
		return null;
	}

	@Override
	public UUID addSubPart(int type) {
		return null;
	}

	@Override
	public void removeSubPart(UUID id) {
	}

	@Override
	public ContentPanel getRepresentation(boolean showConfig, MainController controller) {
		return null;
	}

	@Override
	public IconType getIcon() {
		return null;
	}

	@Override
	public IconType getAddIcon() {
		return null;
	}

	/**
	 * Two tasks are equal if they have the same {@link #getID() id}
	 */
	@Override
	public boolean equals(Object o) {
		if (!(o instanceof Task))
			return false;
		Task that = (Task) o;
		return that.id.equals(this.id);
	}
}
